package fiado.dao.sqlserver;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import fiado.bean.Conta;
import fiado.exception.DaoException;
import fiado.util.DbUtilSqlServer;



public class ContaDAO {

	private static final String QUERY_SEQUENCE = "select isnull(max(NUM_CONTA), 0) + 1 as NOVO_NUM_CONTA from TB_CONTA where ID_PESSOA = ? ";
	
	private static String LISTA_CAMPOS = 
			"	ID_PESSOA, " +
			"	NUM_CONTA, " +
			"	DT_CONTA, " +
			"	VL_TOTAL, " +
			"	STATUS ";
	
	private static final String QUERY_BUSCAR_TODOS = 
			"select " +
				ContaDAO.LISTA_CAMPOS +
			"from " +
			"	TB_CONTA " +
			"order by ID_PESSOA ";
	
	private static final String QUERY_BUSCAR_POR_ID = 
			"select " +
				ContaDAO.LISTA_CAMPOS +
			"from " +
			"	TB_CONTA " +
			"where " +
			"	TB_CONTA.ID_PESSOA = ? and " +
			"	TB_CONTA.NUM_CONTA = ? " +
			"order by ID_PESSOA ";
	
	private static final String QUERY_BUSCAR_POR_ID_PESSOA_E_STATUS = 
		"select " +
			ContaDAO.LISTA_CAMPOS +
		"from " +
		"	TB_CONTA " +
		"where " +
		"	TB_CONTA.ID_PESSOA = ? and " +
		"	TB_CONTA.STATUS = ? " +
		"order by ID_PESSOA ";
	
	private static final String QUERY_APAGAR_POR_ID = 
			"delete " +
			"	from TB_CONTA " +
			"where " +
			"	TB_CONTA.ID_PESSOA = ? and " +
			"	TB_CONTA.NUM_CONTA = ? ";
	
	private static final String QUERY_APAGAR_POR_ID_PESSOA = 
		"delete " +
		"	from TB_CONTA " +
		"where " +
		"	TB_CONTA.ID_PESSOA = ? ";
	
	private static final String QUERY_CRIAR_PRODUTO = 
			"insert into TB_CONTA (" +
				ContaDAO.LISTA_CAMPOS +
			") " +
			"values(" +
			"	?, ?, ?, ?, ?)" ;
	
	private static final String QUERY_ATUALIZAR_PRODUTO = 
			"update TB_CONTA " + 
			"set " + 
			"	DT_CONTA = ?, " +
			"	VL_TOTAL = ?, " +
			"	STATUS = ? " +
			"where " +
			"	TB_CONTA.ID_PESSOA = ? and " +
			"	TB_CONTA.NUM_CONTA = ? ";
	
	private static final String QUERY_BUSCAR_POR_STATUS = 
			"select " +
				ContaDAO.LISTA_CAMPOS +
			"from " +
			"	TB_CONTA " +
			"where " +
			"	STATUS = ? ";
	
	public int getProximoValorSequence(int idPessoa) throws DaoException {
		Connection conn = DbUtilSqlServer.getConnection();
		PreparedStatement statement = null;
		ResultSet result = null;
		int novoNumConta = 0;
		try {
			
			statement = conn.prepareStatement(QUERY_SEQUENCE);
			statement.setInt(1, idPessoa);
			result = statement.executeQuery();
			if (result.next()) {

				novoNumConta = result.getInt("NOVO_NUM_CONTA");
			}
		} catch (SQLException e) {
			throw new DaoException(e);
		} finally {
			DbUtilSqlServer.close(conn, statement, result);
		}
		return novoNumConta;
	}
	
	/**
	 * Este metodo retorna uma lista com todos os objetos Conta armazenados
	 * @return
	 * @throws DaoException 
	 */
	public List<Conta> buscarTodos() throws DaoException {
		Connection conn = DbUtilSqlServer.getConnection();
		PreparedStatement statement = null;
		ResultSet result = null;
		List<Conta> listaTodos = new ArrayList<Conta>();
		try {
			
			statement = conn.prepareStatement(QUERY_BUSCAR_TODOS);
			result = statement.executeQuery();
			while (result.next()) {
				listaTodos.add(getBean(result));
			}
		} catch (SQLException e) {
			throw new DaoException(e);
		} finally {
			DbUtilSqlServer.close(conn, statement, result);
		}
		return listaTodos;
	}

	/**
	 * Este metodo retorna uma lista com todos os objetos Conta armazenados
	 * que possuam <status> no campo status
	 * @return
	 * @throws DaoException 
	 */
	public List<Conta> buscarPorStatus(char status) throws DaoException {
		Connection conn = DbUtilSqlServer.getConnection();
		PreparedStatement statement = null;
		ResultSet result = null;
		List<Conta> listaTodos = new ArrayList<Conta>();
		try {
			
			statement = conn.prepareStatement(QUERY_BUSCAR_POR_STATUS);
			statement.setString(1, "" + status);
			result = statement.executeQuery();
			while (result.next()) {
				listaTodos.add(getBean(result));
			}
		} catch (SQLException e) {
			throw new DaoException(e);
		} finally {
			DbUtilSqlServer.close(conn, statement, result);
		}
		return listaTodos;
	}

	private Conta getBean(ResultSet result) throws SQLException {
		Conta conta = new Conta();
		conta.setIdPessoa(result.getInt("ID_PESSOA"));
		conta.setNumConta(result.getInt("NUM_CONTA"));
		conta.setData(DbUtilSqlServer.getJavaDate(result, "DT_CONTA"));
		conta.setTotal(result.getDouble("VL_TOTAL"));
		conta.setStatus(result.getString("STATUS").charAt(0));
		return conta;
	}
	
	/**
	 * Este metodo retorna o objeto Conta de acordo com os campos chaves
	 * @return
	 * @throws DaoException 
	 */
	public Conta buscarPorId(Conta conta) throws DaoException {
		return buscarPorId(conta.getIdPessoa(), conta.getNumConta());
	}
	
	public Conta buscarPorId(int idPessoa, int numConta) throws DaoException {
		Connection conn = DbUtilSqlServer.getConnection();
		PreparedStatement statement = null;
		ResultSet result = null;
		Conta conta = null;
		try {
			
			statement = conn.prepareStatement(QUERY_BUSCAR_POR_ID);
			statement.setInt(1, idPessoa);
			statement.setInt(2, numConta);
			result = statement.executeQuery();
			if (result.next()) {
				conta = getBean(result);
			}
		} catch (SQLException e) {
			throw new DaoException(e);
		} finally {
			DbUtilSqlServer.close(conn, statement, result);
		}
		return conta;
	}
	
	public List<Conta> buscarPorPessoaEStatus(int idPessoa, char status) throws DaoException {
		Connection conn = DbUtilSqlServer.getConnection();
		PreparedStatement statement = null;
		ResultSet result = null;
		List<Conta> list = new ArrayList<Conta>();
		try {
			
			statement = conn.prepareStatement(QUERY_BUSCAR_POR_ID_PESSOA_E_STATUS);
			statement.setInt(1, idPessoa);
			statement.setString(2, status + "");
			result = statement.executeQuery();
			while (result.next()) {
				Conta conta = getBean(result);
				list.add(conta);
			}
		} catch (SQLException e) {
			throw new DaoException(e);
		} finally {
			DbUtilSqlServer.close(conn, statement, result);
		}
		return list;
	}
	
	/**
	 * Este metodo apaga o objeto Conta de acordo com os campos chave
	 * @throws DaoException 
	 */
	public void apagar(int idPessoa, int numConta) throws DaoException {
		Connection conn = DbUtilSqlServer.getConnection();
		PreparedStatement statement = null;
		ResultSet result = null;
		try {
			
			statement = conn.prepareStatement(QUERY_APAGAR_POR_ID);
			statement.setInt(1, idPessoa);
			statement.setInt(2, numConta);
			statement.execute();
			
		} catch (SQLException e) {
			throw new DaoException(e);
		} finally {
			DbUtilSqlServer.close(conn, statement, result);
		}
	}	
	
	/**
	 * Este metodo apaga o objeto Conta
	 * @throws DaoException 
	 */
	public void apagar(Conta conta) throws DaoException {
		apagar(conta.getIdPessoa(), conta.getNumConta());
	}
	
	/**
	 * Este metodo salva o objeto Conta 
	 * @throws DaoException 
	 */
	public void salvar(Conta conta) throws DaoException {
		Connection conn = DbUtilSqlServer.getConnection();
		PreparedStatement statement = null;
		ResultSet result = null;
		try {
			statement = conn.prepareStatement(QUERY_ATUALIZAR_PRODUTO);
			
			statement.setDate(1, DbUtilSqlServer.getSqlDate(conta.getData()));
			statement.setDouble(2, conta.getTotal());
			statement.setString(3, "" + conta.getStatus());
			
			statement.setInt(4, conta.getIdPessoa());
			statement.setInt(5, conta.getNumConta());

			statement.executeUpdate();
			
		} catch (SQLException e) {
			throw new DaoException(e);
		} finally {
			DbUtilSqlServer.close(conn, statement, result);
		}
	}
	
	/**
	 * Este metodo cria o objeto Conta e retorna o objeto criado com o novo numConta
	 * preenchido
	 * @throws DaoException 
	 */
	public void criar(Conta conta) throws DaoException {
		int novoNumConta = getProximoValorSequence(conta.getIdPessoa());
		conta.setData(new Date());

		Connection conn = DbUtilSqlServer.getConnection();
		PreparedStatement statement = null;
		ResultSet result = null;
		try {
			statement = conn.prepareStatement(QUERY_CRIAR_PRODUTO);
			statement.setInt(1, conta.getIdPessoa());
			statement.setInt(2, novoNumConta);
			statement.setDate(3, DbUtilSqlServer.getSqlDate(conta.getData()));
			statement.setDouble(4, conta.getTotal());
			statement.setString(5, "" + conta.getStatus());

			statement.executeUpdate();
			
			conta.setNumConta(novoNumConta);
			
		} catch (SQLException e) {
			throw new DaoException(e);
		} finally {
			DbUtilSqlServer.close(conn, statement, result);
		}
	}

	public void apagarPorPessoa(int idPessoa) throws DaoException {
		Connection conn = DbUtilSqlServer.getConnection();
		PreparedStatement statement = null;
		ResultSet result = null;
		try {
			
			statement = conn.prepareStatement(QUERY_APAGAR_POR_ID_PESSOA);
			statement.setInt(1, idPessoa);
			statement.execute();
			
		} catch (SQLException e) {
			throw new DaoException(e);
		} finally {
			DbUtilSqlServer.close(conn, statement, result);
		}		
	}


}
